home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / cug236.zip / FCOMP.C < prev    next >
Text File  |  1980-01-02  |  5KB  |  257 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        Compare Text Files;
  4.     DATE:        05/17/1987;
  5.     DESCRIPTION:    "Best version of DIFF (file comparator) from Jan '86
  6.             issue of Software Practice and Experience.";
  7.     VERSION:    1.1;
  8.     KEYWORDS:    File Comparator, File Compare, File Comparison, File
  9.             Comparison Utility;
  10.     FILENAME:    FCOMP.C;
  11.     SEE-ALSO:    DIFF;
  12.     COMPILERS:    vanilla;
  13.     AUTHORS:    Chuck Allison;
  14. */
  15.  
  16. /* fcomp.c:    file comparator that beats DIFF! */
  17.  
  18. #include <stdio.h>
  19.  
  20. /*
  21.  * Portability Note:  8-bit systems often don't have header file string.h.
  22.  * If your system doesn't have it, uncomment the following #define.
  23.  */
  24.  
  25. /*
  26. #define NO_STRING_H
  27. */
  28.  
  29. /*
  30.  * Portability Note:  Back in K & R days, standard library function malloc()
  31.  * was called alloc().    Some compilers (e.g. Eco-C under CP/M) haven't made
  32.  * the name change.  If yours is one of these compilers, uncomment the
  33.  * following #define:
  34.  */
  35.  
  36. /*
  37. #define malloc(p)    alloc(p)
  38. */
  39.  
  40. /*
  41.  * Portability Note:  The AZTEC C compilers handle the binary/text file
  42.  * dichotomy differently from most other compilers.  Uncomment the following
  43.  * pair of #defines if you are running AZTEC C:
  44.  */
  45.  
  46. /*
  47. #define getc(f)        agetc(f)
  48. #define putc(c,f)    aputc(c,f)
  49. */
  50.  
  51. #ifdef    NO_STRING_H
  52. int strcmp(), strlen();
  53. #else
  54. #include <string.h>
  55. #endif
  56.  
  57. #define MAXLINES 1000
  58. #define ORIGIN MAXLINES
  59. #define INSERT 1
  60. #define DELETE 2
  61.  
  62. struct edit {
  63.    struct edit *link;
  64.    int op;
  65.    int line1;
  66.    int line2;
  67. };
  68.  
  69. char *A[MAXLINES], *B[MAXLINES];
  70.  
  71. void exit();
  72.  
  73. void main(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.    int     col, d, k, lower, m, max_d, n, row, upper;
  78.    int last_d[2*MAXLINES+1];
  79.    struct edit *new, *script[2*MAXLINES+1];
  80.    char *malloc();
  81.    int atoi(), in_file();
  82.    void exceed(), fatal(), put_scr();
  83.  
  84.    if (argc > 1 && argv[1][0] == '-')
  85.    {
  86.       max_d = atoi(&argv[1][1]);
  87.       ++argv;
  88.       --argc;
  89.    }
  90.    else
  91.       max_d = 2*MAXLINES;
  92.  
  93.    if(argc != 3)
  94.       fatal("fcomp requires two file names.");
  95.  
  96.    m = in_file(argv[1],A);
  97.    n = in_file(argv[2],B);
  98.  
  99.    for (row=0 ; row<m && row < n && strcmp(A[row],B[row]) == 0 ; ++row)
  100.       ;
  101.    last_d[ORIGIN] = row;
  102.    script[ORIGIN] = NULL;
  103.    lower = (row == m) ? ORIGIN + 1 : ORIGIN - 1;
  104.    upper = (row == n) ? ORIGIN - 1 : ORIGIN + 1;
  105.    if (lower > upper)
  106.    {
  107.       puts("The files are identical.");
  108.       exit(0);
  109.    }
  110.  
  111.    for (d = 1 ; d <= max_d ; ++d)
  112.    {
  113.       for ( k = lower ; k <= upper ; k +=2)
  114.       {
  115.      new = (struct edit *) malloc(sizeof(struct edit));
  116.      if (new == NULL)
  117.         exceed(d);
  118.  
  119.      if (k == ORIGIN-d || k != ORIGIN+d && last_d[k+1] >= last_d[k-1])
  120.      {
  121.         row = last_d[k+1]+1;
  122.         new->link = script[k+1];
  123.         new->op = DELETE;
  124.      }
  125.      else
  126.      {
  127.         row = last_d[k-1];
  128.         new->link = script[k-1];
  129.         new->op = INSERT;
  130.      }
  131.      new->line1 = row;
  132.      new->line2 = col = row + k - ORIGIN;
  133.      script[k] = new;
  134.  
  135.      while(row < m && col < n && strcmp(A[row],B[col]) == 0)
  136.      {
  137.         ++row;
  138.         ++col;
  139.      }
  140.      last_d[k] = row;
  141.  
  142.      if (row == m && col == n)
  143.      {
  144.         put_scr(script[k]);
  145.         exit(!0);
  146.      }
  147.      if (row == m)
  148.         lower = k+2;
  149.  
  150.      if (col == n)
  151.         upper = k-2;
  152.       }
  153.       --lower;
  154.       ++upper;
  155.    }
  156.    exceed(d);
  157. }
  158.  
  159. int in_file(filename,P)
  160. char *filename, *P[];
  161. {
  162.    char buf[100], *malloc(), *save, *b;
  163.    FILE *fp;
  164.    int lines = 0;
  165.    void fatal();
  166.  
  167.    if ((fp = fopen(filename,"r")) == NULL)
  168.    {
  169.       fprintf(stderr, "Cannot open file %s.\n",filename);
  170.       exit(!0);
  171.    }
  172.  
  173.    while(fgets(buf,100,fp) != NULL)
  174.    {
  175.       if (lines >= MAXLINES)
  176.      fatal("File is too large for diff.");
  177.       if ((save = malloc(strlen(buf)+1)) == NULL)
  178.      fatal("Not enough room to save the files.");
  179.       P[lines++] = save;
  180.       for (b = buf ; *save++ = *b++ ; )
  181.      ;
  182.    }
  183.    fclose(fp);
  184.    return(lines);
  185. }
  186.  
  187. void put_scr(start)
  188. struct edit *start;
  189. {
  190.    struct edit *ep, *behind, *ahead, *a, *b;
  191.    int change;
  192.  
  193.    ahead = start;
  194.    ep = NULL;
  195.    while (ahead != NULL)
  196.    {
  197.       behind = ep;
  198.       ep = ahead;
  199.       ahead = ahead->link;
  200.       ep->link = behind;
  201.    }
  202.  
  203.    while( ep != NULL)
  204.    {
  205.       b = ep;
  206.       if (ep->op == INSERT)
  207.      printf("Inserted after line %d:\n",ep->line1);
  208.       else
  209.       {
  210.      do
  211.      {
  212.         a = b;
  213.         b = b->link;
  214.      } while (b!=NULL && b->op == DELETE && b->line1 == a->line1+1);
  215.  
  216.      change = (b!=NULL && b->op == INSERT && b->line1 == a->line1);
  217.      if (change)
  218.         printf("\nChanged ");
  219.      else
  220.         printf("\nDeleted ");
  221.      if (a == ep)
  222.         printf("line %d\n",ep->line1);
  223.      else
  224.         printf("lines %d-%d:\n",ep->line1,a->line1);
  225.  
  226.      do
  227.      {
  228.         printf(" %s",A[ep->line1-1]);
  229.         ep = ep->link;
  230.      } while (ep != b);
  231.  
  232.      if (!change)
  233.         continue;
  234.      printf("To:\n");
  235.       }
  236.       do
  237.       {
  238.      printf(" %s",B[ep->line2-1]);
  239.      ep = ep->link;
  240.       } while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1);
  241.    }
  242. }
  243.  
  244. void fatal(msg)
  245. char *msg;
  246. {
  247.    fprintf(stderr,"%s\n",msg);
  248.    exit(!0);
  249. }
  250.  
  251. void exceed(d)
  252. int d;
  253. {
  254.    fprintf(stderr,"The files differ in at least %d lines. \n",d);
  255.    exit(!0);
  256. }
  257.